import { Inject } from '../decorates/inject';
import { createDom } from '../utils/index';
import { IFont, IBorder, IBorderStyle } from '../interfaces/styles';
import { Observable, Subject } from 'rxjs';
import { getValue } from '../utils/catch-cell'
type TSubNames = 'afterDomInit';
@Inject()
export class Draw{
    public container: HTMLElement;
    public dataCas: HTMLCanvasElement;
    public operateCas: HTMLCanvasElement;
    public extraContent: HTMLElement;
    public sub: Subject<TSubNames> = new Subject();
    constructor() {
    }
    public getCasSize() {
        return {
            width: this.dataCas.width,
            height: this.dataCas.height
        }
    }
    public setContainer(container: HTMLElement) {
        this.container = container;
        const stl = {
            position: 'absolute',
            top: '0px',
            left: '0px'
        }
        const attr = {
            'class': 'zxlsx-main-canvas', 
            'height': this.container.clientHeight, 
            'width': this.container.clientWidth
        }
        this.dataCas = createDom('canvas', Object.assign(stl, {'z-index': 1}), attr) as HTMLCanvasElement;
        this.container.appendChild(this.dataCas);
        this.extraContent = createDom('div', {}, {'class': 'zxlsx-extra-content'});
        this.container.appendChild(this.extraContent);
        this.operateCas = createDom('canvas', Object.assign(stl, {'z-index': 2}), attr) as HTMLCanvasElement;
        this.container.appendChild(this.operateCas);
        this.sub.next('afterDomInit');
    }
    public resize() {
        try {
            let height = this.container.clientHeight.toString();
            let width = this.container.clientWidth.toString();
            this.dataCas.setAttribute('height',height);
            this.dataCas.setAttribute('width',width);
            this.operateCas.setAttribute('height',height);
            this.operateCas.setAttribute('width',width);            
        } catch (error) {
            
        }
    }
    public drawCell(border: IBorder) {

    }
    public rect(x: number, y: number, width: number, height: number, font: (IFont | null), style: {bgClr?: string, border?: Partial<IBorder<IBorderStyle>>}) {
        let ctx = this.dataCasCtx;
        ctx.save();
        ctx.beginPath();
        ctx.clearRect(x - 1,y - 1, width - 1, height - 1);
        ctx.restore();
        ctx.save();
        ctx.beginPath();
        if(style.bgClr != undefined) {
            ctx.fillStyle= style.bgClr;
        }
        ctx.fillRect(x,y, width - 1, height - 1);
        ctx.restore();
        // 绘制上边框
        if(style.border != undefined) {
            if(style.border.top != undefined) {
                this.line({x: x - 1, y: y - 1}, {x: x + width - 1, y: y - 1}, style.border.top);
            }
            if(style.border.left != undefined) {
                this.line({x: x - 1, y: y - 1}, {x: x - 1, y: y+ height -1}, style.border.left);
            }
            if(style.border.left != undefined) {
                
            }
            if(style.border.bottom != undefined) {

            }
        }
        // 绘制文字
        if(font != null && font.content != undefined && font.content != null && font.content != '') {
            this.fillText({
                x: x,
                y: y,
                width: width,
                height: height,
            },font);         
        }
    }
    public line(start: {x: number, y: number}, end: {x: number, y: number}, option: IBorderStyle, ctx: CanvasRenderingContext2D = this.dataCasCtx) {
        ctx.save();
        ctx.beginPath();
        ctx.strokeStyle = option.color;   
        ctx.moveTo(start.x+0.5, start.y+0.5);
        ctx.lineTo(end.x+0.5, end.y+0.5);
        ctx.lineWidth = option.width;
        ctx.stroke();
        ctx.restore();
    }
    /**
     * 
     * @param str 
     * @param options 
     * @param style 
     * @description textAlign textBaseline, fillStyle
     */
    protected fillText(containerSize: {x: number, y: number, width: number, height: number}, font: IFont) {
        let ctx = this.dataCasCtx;
        ctx.save();
        let baseLinePostion = {x: containerSize.x, y: containerSize.y};
        ctx.rect(containerSize.x - 1, containerSize.y - 1, containerSize.width - 2, containerSize.height - 2);
        ctx.clip();
        if(ctx.measureText(<string>font.content).width > containerSize.width) {
            ctx.textAlign = 'start';
            baseLinePostion.x = containerSize.x + 1;
        }else{
            switch (font.horizontal) {
                case 'left':
                    ctx.textAlign = 'start';
                    baseLinePostion.x = containerSize.x + 1;
                    break;
                case 'right':
                    baseLinePostion.x = containerSize.x + containerSize.width - 3;
                    ctx.textAlign = 'right';
                    break;
                case 'center':
                    baseLinePostion.x = containerSize.x + containerSize.width / 2;
                    ctx.textAlign = 'center';
                    break;
                default:
                    break;
            }            
        }
        if(<number>font.size > containerSize.height) {
            
            ctx.textBaseline="middle";
            baseLinePostion.y = containerSize.y + containerSize.height / 2;
        }else{
            switch(font.vertical) {
                case 'top':
                    ctx.textBaseline="top";
                    baseLinePostion.y = containerSize.y + 1;
                    break;
                case 'middle':
                    ctx.textBaseline="middle";
                    baseLinePostion.y = containerSize.y + containerSize.height / 2;
                    break;
                case 'bottom':
                    ctx.textBaseline="bottom";
                    baseLinePostion.y = containerSize.y + containerSize.height - 1;
                    break;
                default:
                    break;
            }            
        }
        ctx.font= `${font.size}px ${font.family}`;
        ctx.fillText(<string>font.content,baseLinePostion.x + 0.5, baseLinePostion.y + 0.5);
        ctx.restore();
    }
    /**
     * @description 检查字体宽度
     */
    public measureText() {

    }
    protected get dataCasCtx() {
        return this.dataCas.getContext('2d') as CanvasRenderingContext2D;
    }
    protected get operateCasCtx() {
        return this.dataCas.getContext('2d')  as CanvasRenderingContext2D;
    }
}
interface IFillTextOptions {
    maxWidth: number,
    maxHeight: number
}